package net.keebook.webapp.bean;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.servlet.http.HttpServletResponse;

import net.keebook.webapp.dao.GroupDao;
import net.keebook.webapp.dao.KeeBookDao;
import net.keebook.webapp.dao.PasswordDao;
import net.keebook.webapp.dao.SettingDao;
import net.keebook.webapp.entity.PasswordItem;
import net.keebook.webapp.model.SessionModel;
import net.keebook.webapp.util.AccessRight;
import net.keebook.webapp.util.AesCrypto;
import net.keebook.webapp.util.DatabaseExport;
import net.keebook.webapp.util.ExportCsv;
import net.keebook.webapp.util.ExportXls;

import org.apache.commons.fileupload.FileUploadException;
import org.apache.log4j.Logger;

@ManagedBean
@RequestScoped
public class ExportBean {
	private String fileFormat;
	private String encryptionPassword;
	@Inject
	private GroupDao groupDao;
	@Inject
	private PasswordDao passwordDao;
	@Inject
	private SettingDao settingDao;
	@Inject
	private KeeBookDao keeBookDao;
	private SessionModel sessionModel;
	
	@PostConstruct
	public void init() throws IOException {
		setSessionModel(SessionModel.getInstance(FacesContext.getCurrentInstance()));
		
		if (!getKeeBookDao().getKeeBookAccess(getSessionModel(), AccessRight.READ_ONLY))  {
			Logger.getLogger(this.getClass()).warn("Forbidden access to bean from userId="+getSessionModel().getUserId());
			FacesContext.getCurrentInstance().getExternalContext().redirect("403.xhtml");
			return;
		}
	}
	
	private DatabaseExport getExportInstance(String extension) {
		if (extension == null || "".equals(extension)) {
			return null;
		}
		extension = extension.toLowerCase();
		if ("csv".equals(extension)) {
			return new ExportCsv();
		}
		if ("xls".equals(extension)) {
			return new ExportXls();
		}
		if ("kdb".equals(extension)) {
			// TODO keepass4j is not capable of adding items/creating new databases.
		}
		return null;
	}
	
	private String decrypt(String s) {
		try {
			return AesCrypto.decrypt(s, getEncryptionPassword());
		} catch (Exception e) {
			return "";
		}
	}
	
	private List<PasswordItem> getDecryptedItems(List<PasswordItem> encryptedList) {
		List<PasswordItem> items = new ArrayList<PasswordItem>();
		try {
			for (PasswordItem encryptedItem : encryptedList) {
				PasswordItem item = encryptedItem.clone();
				item.setUsername(decrypt(item.getUsername()));
				item.setPassword(decrypt(item.getPassword()));
				item.setNotes(decrypt(item.getNotes()));
				item.setUrl(decrypt(item.getUrl()));
				items.add(item);
			}
		} catch (Exception e) {
			// Should not happen...
		}
		return items;
	}
	
	public void process() throws IOException, FileUploadException {
		if (!getKeeBookDao().getKeeBookAccess(getSessionModel(), AccessRight.READ_ONLY))  {
			Logger.getLogger(this.getClass()).warn("Forbidden access to bean from userId="+getSessionModel().getUserId());
			FacesContext.getCurrentInstance().getExternalContext().redirect("403.xhtml");
			return;
		}
		
		HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
		DatabaseExport databaseExport = getExportInstance(getFileFormat());
		databaseExport.setOutputStream(response.getOutputStream());
		databaseExport.setKeeBook(getKeeBookDao().get(getSessionModel().getKeeBookId()));
		databaseExport.setItems(getDecryptedItems(getPasswordDao().getList(getSessionModel().getUserId(), getSessionModel().getKeeBookId())));
		response.reset();
		response.setContentType("application/force-download");
		response.setHeader("Content-disposition", "attachment; filename=\"" + databaseExport.getFileName() + "\""); 
		databaseExport.export();
		FacesContext.getCurrentInstance().responseComplete();
	}

	public String getFileFormat() {
		return fileFormat;
	}

	public void setFileFormat(String fileFormat) {
		this.fileFormat = fileFormat;
	}

	public GroupDao getGroupDao() {
		return groupDao;
	}

	public void setGroupDao(GroupDao groupDao) {
		this.groupDao = groupDao;
	}

	public PasswordDao getPasswordDao() {
		return passwordDao;
	}

	public void setPasswordDao(PasswordDao passwordDao) {
		this.passwordDao = passwordDao;
	}

	public String getEncryptionPassword() {
		return encryptionPassword;
	}

	public void setEncryptionPassword(String encryptionPassword) {
		this.encryptionPassword = encryptionPassword;
	}

	public SettingDao getSettingDao() {
		return settingDao;
	}

	public void setSettingDao(SettingDao settingDao) {
		this.settingDao = settingDao;
	}

	public SessionModel getSessionModel() {
		return sessionModel;
	}

	public void setSessionModel(SessionModel sessionModel) {
		this.sessionModel = sessionModel;
	}

	public KeeBookDao getKeeBookDao() {
		return keeBookDao;
	}

	public void setKeeBookDao(KeeBookDao keeBookDao) {
		this.keeBookDao = keeBookDao;
	}
	
}
